package com.hp.provider.config;


import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONReader;
import com.alibaba.fastjson2.JSONWriter;
import com.alibaba.fastjson2.support.config.FastJsonConfig;
import com.alibaba.fastjson2.support.spring.http.converter.FastJsonHttpMessageConverter;
import com.hp.common.common.Result;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.List;

/**
 * @author dongxing
 **/
@Configuration
@Slf4j
public class WebMvcConfigure implements WebMvcConfigurer {


    /**
     * 直接将 默认的 jackson 替换为 fastjson
     *
     * @param converters 转换器
     */
    @Override
    public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
        final int size = converters.size();
        for (int i = 0; i < size; i++) {
            if (converters.get(i).getClass() == MappingJackson2HttpMessageConverter.class) {
                converters.set(i, fastJsonHttpMessageConverter());
            }
        }
    }

    private FastJsonHttpMessageConverter fastJsonHttpMessageConverter() {
        // 1、需要先定义一个 convert 转换消息的对象;
        FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter();

        //List<MediaType> supportedMediaTypes = new ArrayList<>();
        ////提供对admin的类型支持mediaType
        //MediaType mediaType = MediaType.valueOf("application/vnd.spring-boot.actuator.v2+json");
        //supportedMediaTypes.add(mediaType);
        //supportedMediaTypes.add(MediaType.ALL);
        //fastConverter.setSupportedMediaTypes(supportedMediaTypes);

        //2、添加fastJson 的配置信息，比如：是否要格式化返回的json数据;
        FastJsonConfig fastJsonConfig = new FastJsonConfig();

        //自定义配置...
        // 反序列化配置
        fastJsonConfig.setReaderFeatures(JSONReader.Feature.FieldBased, // 不配置，会默认基于public的field和getter方法序列化.配置后，会基于非static的field（包括private）做反序列化。在fieldbase配置下会更安全
                JSONReader.Feature.TrimString, // 对读取到的字符串值做trim处理
                JSONReader.Feature.DuplicateKeyValueAsArray, // 重复Key的Value不是替换而是组合成数组
                JSONReader.Feature.SupportArrayToBean); // 支持数据映射的方式
        // 序列化配置
        fastJsonConfig.setWriterFeatures(JSONWriter.Feature.FieldBased, // 不配置，会默认基于public的field和getter方法序列化.配置后，会基于非static的field（包括private）做反序列化。在fieldbase配置下会更安全
                JSONWriter.Feature.WriteMapNullValue, //保留空的字段
                JSONWriter.Feature.WriteNullStringAsEmpty,//String null -> ""
                JSONWriter.Feature.WriteNullNumberAsZero,//Number null -> 0
                JSONWriter.Feature.WriteEnumUsingToString,//enm -> string
                JSONWriter.Feature.WriteNullListAsEmpty,//list -> []
                JSONWriter.Feature.WriteBooleanAsNumber,//boolean -> true输出为1，false输出为0
                JSONWriter.Feature.PrettyFormat);//结果格式化
        // 全局处理精度丢失问题，一般局部处理
        //fastJsonConfig.setSerializeFilters((ValueFilter) (object, name, value) -> {
        //    if (value instanceof Long || value instanceof BigDecimal) // 解决long和 bigDecimal精度丢失问题
        //        return value.toString();
        //    return value;
        //});

        // 添加 数据脱敏的拦截器
        //fastJsonConfig.setWriterFilters((ValueFilter) (object, name, value) -> {
        //
        //    if (!(value instanceof String) || ((String) value).length() == 0) {
        //        return value;
        //    }
        //    try {
        //        Field field = object.getClass().getDeclaredField(name);
        //        Sensitive sensitive;
        //        if (String.class != field.getType() || (sensitive = field.getAnnotation(Sensitive.class)) == null) {
        //            return value;
        //        }
        //        String valueStr = (String) value;
        //        final SensitiveStrategy sensitiveStrategy = sensitive.strategy();
        //        return sensitiveStrategy.getDesensitize().apply(valueStr);
        //    } catch (NoSuchFieldException e) {
        //        log.error("当前数据类型为: {},值为: {}", object.getClass(), value);
        //        return value;
        //    }
        //});

        //BigDecimal格式化
        //SerializeConfig serializeConfig = SerializeConfig.getGlobalInstance();
        //serializeConfig.put(BigDecimal.class, CustomerBigDecimalCodec.INSTANCE);
        //fastJsonConfig.setSerializeConfig(serializeConfig);

        //3、在convert中添加配置信息.
        fastConverter.setFastJsonConfig(fastJsonConfig);
        fastConverter.setDefaultCharset(StandardCharsets.UTF_8);
        fastConverter.setSupportedMediaTypes(Collections.singletonList(MediaType.APPLICATION_JSON));
        return fastConverter;
    }

    // @Bean
    // public HttpMessageConverters fastJsonHttpMessageConverters() {
    //     // 1、需要先定义一个 convert 转换消息的对象;
    //     FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter();

    //     //2、添加fastJson 的配置信息，比如：是否要格式化返回的json数据;
    //     FastJsonConfig fastJsonConfig = new FastJsonConfig();
    //     fastJsonConfig.setSerializerFeatures(SerializerFeature.WriteMapNullValue,//保留空的字段
    //             SerializerFeature.WriteNullStringAsEmpty,//String null -> ""
    //             SerializerFeature.WriteNullNumberAsZero,//Number null -> 0
    //             SerializerFeature.WriteEnumUsingToString,//enm -> string
    //             SerializerFeature.DisableCircularReferenceDetect,//禁止循环引用
    //             SerializerFeature.SortField,//排序的序列
    //             SerializerFeature.PrettyFormat);//结果格式化

    //     // 全局处理精度丢失问题，一般是局部处理
    //     // fastJsonConfig.setSerializeFilters((ValueFilter) (object, name, value) -> {
    //     //     if (value instanceof Long || value instanceof BigDecimal) // 解决long和 bigDecimal精度丢失问题
    //     //         return value.toString();
    //     //     return value;
    //     // });

    //     //3、在convert中添加配置信息.
    //     fastConverter.setFastJsonConfig(fastJsonConfig);

    //     HttpMessageConverter<?> converter = fastConverter;
    //     return new HttpMessageConverters(converter);
    // }



    /**
     * 统一认证拦截
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new HandlerInterceptor() {
            @Override
            public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

                //验证签名、数据验证
                log.info("签名认证，请求接口：{}，请求参数：{}", request.getRequestURI(), JSON.toJSONString(request.getParameterMap()));
                boolean pass = validateSign(request);
                if (true) {
                    return true;
                } else {
                    log.error("签名认证失败，请求接口：{}",request.getRequestURI());
                    Result<Object> codeMessage = Result.createByErrorCodeMessage(Result.ResponseCode.ERROR_SIGNATURE.getCode(), "签名认证失败");
                    responseResult(response, codeMessage);
                    return false;
                }
            }
        }).excludePathPatterns("/swagger-resources/**", "/webjars/**", "/v2/**", "/swagger-ui.html/**");
    }

    private void responseResult(HttpServletResponse response, Result result) {
        response.setCharacterEncoding("UTF-8");
        response.setHeader("Content-type", "application/json;charset=UTF-8");
        response.setStatus(200);
        try {
            response.getWriter().write(JSON.toJSONString(result));
        } catch (IOException ex) {
            log.error(ex.getMessage());
        }
    }


    /**
     * 签名认证
     */
    private boolean validateSign(HttpServletRequest request) {
        //请求报文
        String logisticsInterface=request.getParameter("logistics_interface");
        //报文签名
        String requestSign = request.getParameter("data_digest");
        //请求来源
        String fromCode=request.getParameter("from_code");
        if(StringUtils.isEmpty(requestSign)||StringUtils.isEmpty(logisticsInterface)) {
            return false;
        }
        try {
//            List<AppSecretProperties.Config> appConfig = appSecretProperties.getAppConfig();
//            if (Optional.ofNullable(appConfig).isPresent() && !appConfig.isEmpty()) {
//                Optional<AppSecretProperties.Config> any = appConfig.stream()
//                        .filter(e -> e.getAppId().equals(fromCode)).findAny();
//                return !any.isPresent() || !requestSign.equals(Base64Util.encode(MD5Util.MD5(logisticsInterface + any.get().getSecret()).getBytes()));
//
//            }
            return true;
        } catch (Exception e) {
            log.error("签名认证失败，exception:",e.getMessage());
            return false;
        }
    }

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("swagger-ui.html")
                .addResourceLocations("classpath:/META-INF/resources/");

        registry.addResourceHandler("/webjars/**")
                .addResourceLocations("classpath:/META-INF/resources/webjars/");
    }
}
